# coding=utf-8
import json
import math
import random
import csv
import ctypes
from tkinter.constants import PROJECTING
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import configparser


# from .import view_map as vm
# from .import base_fun as fun
# from .import networkx_graph as xgh

import view_map as vm
import base_fun as fun
import networkx_graph as xgh

colors = list(dict(mcolors.BASE_COLORS, **mcolors.CSS4_COLORS).keys())


def filter_people():
    with open("./data/data2cpp.json", 'r') as load_f:
        load_dict = json.load(load_f)

    rescue_peoples = [[], [], []]

    for idex in range(len(load_dict["car_points"])):
        for point in load_dict["car_points"][idex]["pass_points"]:
            rescue_peoples[idex].append(
                [point["longitude"], point["latitude"]])
    # print(rescue_peoples)
    datasets = (np.array(rescue_peoples[0]), np.array(
        rescue_peoples[1]), np.array(rescue_peoples[2]))

    for idex in range(3):
        # plt.figure() #另起一张新的画布
        plt.plot(datasets[idex][:, 1], datasets[idex][:, 0],
                 color=colors[idex], label='t2', marker='o')

    # plt.show()
    return datasets


def GetDistance(p1, p2):
    lat1 = p1[1]
    long1 = p1[0]
    lat2 = p2[1]
    long2 = p2[0]
    return GetDistance2(lat1, long1, lat2, long2)


def GetDistance2(lat1, long1, lat2, long2):
    # print(lat1, long1, lat2, long2)
    val = math.sin(lat1 * 0.01745329) * math.sin(lat2 * 0.01745329) + math.cos(lat1 *
                                                                               0.01745329) * math.cos(lat2 * 0.01745329) * math.cos((long1 - long2) * 0.01745329)
    return 6378137 * math.acos(val)


def cal_cost(lstt, point):
    minval = []
    minlist = []
    for j in range(20):
        sum = 0
        ls = list(lstt)
        for i in range(len(ls)-1):
            sum += GetDistance(point[ls[i]], point[ls[i+1]])
        # print(sum)
        minval.append(sum)
        minlist.append(ls)
        random.shuffle(lstt)
    ret_ls = minlist[minval.index(min(minval))]
    return min(minval), minval.index(min(minval)), ret_ls


def cal_cost(lstt, point):
    minval = []
    minlist = []
    for j in range(20):
        sum = 0
        ls = list(lstt)
        for i in range(len(ls)-1):
            sum += GetDistance(point[ls[i]], point[ls[i+1]])
        # print(sum)
        minval.append(sum)
        minlist.append(ls)
        random.shuffle(lstt)
    ret_ls = minlist[minval.index(min(minval))]
    return min(minval), minval.index(min(minval)), ret_ls


def calpath(txdatx):

    dlen = len(txdatx)
    minindex = txdatx[0]  # min(txdatx)
    new_list = []
    new_list.append(minindex)  # listname[index]
    # print(new_list, txdatx.index(min(txdatx)))
    del txdatx[0]  # txdatx.index(min(txdatx))
    # print(min(txdatx))
    dis = []
    while(len(txdatx) > 0):
        for idd in range(len(txdatx)):
            dis.append(GetDistance2(
                txdatx[idd][0], txdatx[idd][1], minindex[0], minindex[1]))
        minindex = txdatx[dis.index(min(dis))]
        new_list.append(minindex)
        del txdatx[dis.index(min(dis))]
        dis = []
    data2 = pd.DataFrame(new_list, columns=[
                         'longitude', 'latitude', 'label', 'people_id'])
    return data2


def msort(txdatx):
    newlis = list(txdatx)
    ret = calpath(newlis)
    # print(txdatx)
    return ret


def sesson2_2_main(round_id):
    rp, center = fun.out_data(round_id)  # 计算待救人ID

    d1 = rp[0]  # .sample(n=75)
    d2 = rp[1]  # .sample(n=75)
    d3 = rp[2]  # .sample(n=75)

    sd1 = np.array(d1).tolist()  # np.ndarray()
    sd2 = np.array(d2).tolist()  # np.ndarray()
    sd3 = np.array(d3).tolist()  # np.ndarray()
    sd0 = (msort(sd1), msort(sd2), msort(sd3))
    # fun.toJons(addd, "./data/data2cpp.json")
    # fun.toJonsPeolpes(sd0)
    # gen_people_path()
    # points = fun.view_maps(True)
    # filter_people()  # 过滤一些
    # read_txt()
    # plt.show()
    xgh._main_fun(sd0, round_id)

    return True


def read_txt():
    fname = 'outpath.csv'
    points = fun.view_maps(False)
    paths = [[], [], []]
    point_ids = [[], [], []]
    with open(fname, 'r+', encoding='utf-8') as txtf:
        lines = txtf.readlines()
        # print(len(lines))

    for index, line in enumerate(lines):
        point_ids[index] = (list(int(i) for i in line.split(",")))

    for index in range(3):
        #         # print(line)

        for val in point_ids[1]:
            paths[index].append(points[val])
    data1 = pd.DataFrame(paths[0], columns=['x', 'y'])
    data2 = pd.DataFrame(paths[1], columns=['x', 'y'])
    data3 = pd.DataFrame(paths[2], columns=['x', 'y'])
    fun.toJons((data1, data2, data3), './data/send_data.json')


def view_my_path(paths):
    for idex, path in enumerate(paths):
        data = np.array(path)
        plt.plot(data[:, 1], data[:, 0],
                 color=colors[idex+3], label='t2'+str(idex), marker='.')
    # plt.show()


def view_randm_path():
    # gen_people_path()
    points = fun.view_maps(True)
    path = []
    paths = []
    point_id = []
    point_ids = []
    fname = 'C:\\Users\\tang\\Desktop\\RHZT\R1\\jsontest3\\outrandmpath.csv'
    with open(fname, 'r+', encoding='utf-8') as txtf:
        lines = txtf.readlines()
    for index, line in enumerate(lines):
        point_ids.append(list(int(i) for i in line.split(",")))
    for index, val in enumerate(point_ids):
        for val in val:
            path.append(points[val])
        paths.append(path)
        path = []
    # print(paths)

    view_my_path(paths)

    filter_people()


def gen_people_path():
    # gen_path = "C:\\Users\\tang\\Desktop\\cmd\\cpp_app\\data\\gen_people_25.csv"
    gen_path = "C:\\Users\\tang\\Desktop\\cmd\\data\\gen_people_25.csv"
    # test_dll = ctypes.cdll.LoadLibrary(
    #     'C:\\Users\\tang\\Desktop\\cmd\\cpp_app\\x64\\Release\\jsontest.dll')
    # ret = test_dll.gen_people_25(1000)
    # print(ret)
    gen_paths(
        reapath=gen_path,
        out_path='C:\\Users\\tang\\Desktop\\RHZT\\Test_Exam\\session\\session_2\\subject_2\\team_path_2.json'
    )


def gen_different_path():
    gen_path = "C:\\Users\\tang\\Desktop\\cmd\\cpp_app\\data\\gen_people_25.csv"
    test_dll = ctypes.cdll.LoadLibrary(
        'C:\\Users\\tang\\Desktop\\cmd\\cpp_app\\x64\\Release\\jsontest.dll')
    ret = test_dll.gen_differnent_paths(10, 15000, 10)
    print(ret)
    gen_paths(
        reapath=gen_path,
        out_path='C:\\Users\\tang\\Desktop\\RHZT\\Test_Exam\\session\\session_2\\subject_2\\team_path_02.json'
    )


def gen_paths(reapath, out_path):
    points = fun.view_maps(False)
    paths = [[], [], []]
    point_ids = [[], [], []]
    with open(reapath, 'r+', encoding='utf-8') as txtf:
        lines = txtf.readlines()
        # print(len(lines))

    for index, line in enumerate(lines):
        point_ids[index] = (list(int(i) for i in line.split(",")))

    for index in range(3):
        for val in point_ids[index]:
            paths[index].append(points[val])

    data1 = pd.DataFrame(paths[0], columns=['y', 'x'])
    data2 = pd.DataFrame(paths[1], columns=['y', 'x'])
    data3 = pd.DataFrame(paths[2], columns=['y', 'x'])
    # print(out_path)
    fun.toJons((data1, data2, data3), out_path)


# Ui界面调用进行预处理


def preprocess(Objdll, s1, ipconfigPath):
    # 读图
    cf = configparser.ConfigParser()
    cf.read(ipconfigPath+"/ipconfig.ini")
    local_ip = cf.get("entrant", "ip")
    local_port = cf.get("entrant", "port")
    s1.bind((local_ip, int(local_port)))  # 绑定ip和端口
    # 设置发送（客户端）的ip和端口
    client_ip = cf.get("client", "ip")
    client_port = cf.get("client", "port")
    dest_dir = (client_ip, int(client_port))
    Globalvar.set_send_id_addr(dest_dir)
    # local_ip = udp.socket.gethostbyname(udp.socket.gethostname())
    # s1.bind((local_ip, 10014))
    # print("local_ip:",local_ip)
    print('Bind UDP on 10014...')
    # 创建线程接收数据
    recv_thread = udp.threading.Thread(target=udp.recvmsg, args=(s1, Objdll))
    recv_thread.start()
    return True
# Ui界面调用运行科目1


def session2_2_main(Objdll, s):
    exam_round = 1
    # 判断每场考试是否结束，结束为true，否则为false，初始为true方便第一次发送
    finish = True
    while True:
        if finish:
            # 发送准备指令
            sesson1.send_ready(2, 2, exam_round, s)
            finish = False
        if Globalvar.get_recv_msg_content():
            Globalvar.set_recv_msg_content(False)
            # 根据报文读取对应科目、情景下的client_path_.json文件
            temp_content = Globalvar.get_msg_content_value()
            examRound = Globalvar.get_exam_round()
            sesson2_2_main(examRound)  # 计算结果
            # 数据传入完成，算法计算完毕，向平台发送完成指令
            udp.sentmsg(temp_content[0], temp_content[1], s, Globalvar.get_send_id_addr(
            ), exam_round=examRound, info=3)
            finish = True
            # 一场考试结束后将考试场次+1
            exam_round += 1
            print("运行成功，准备下次考试")


if __name__ == '__main__':
    sesson2_2_main(2)
    # vm.show_gen_22_path()
    
